/*
 * Copyright (c) 2025 Li Auto Inc. and its affiliates
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <string>
#include <map>
#include <memory>
#include <mutex>
#include <boost/interprocess/sync/interprocess_mutex.hpp>

#include <transport/TransportInterface.h>

#include <transport/TransportDescriptorInterface.h>
#include <deps/common/IPFinder.h>
#include <deps/common/IPLocator.h>

#include <udp/UDPv4Transport.h>
#include <transport/TransportFactory.hpp>
#include <ertps/utils/collections/ResourceLimitedVector.hpp>

namespace vbs {
namespace transport {
using namespace vbsutil::xmlparser;

TransportFactory::TransportFactory() : mtx_transport_() {}

TransportFactory::~TransportFactory() {
    {
        std::unique_lock<std::mutex> lock(mtx_transport_);
        for (auto& array_it : mRegisteredTransports) {
            for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
                Transport* transport = array_it.second.at(i);
                if (transport) {
                    array_it.second.at(i) = nullptr;
                    transport->m_receiverResourceList_.clear();
                    transport->m_sendResourceList_.clear();
                    delete transport->transmitor_;
                    delete transport;
                }
            }
        }
        mRegisteredTransports.clear();
    }
}

std::shared_ptr<TransportFactory> TransportFactory::get_instance() {
    // Note we need a custom deleter, since the destructor is protected.
    static const std::shared_ptr<TransportFactory> instance(new TransportFactory(),
                                                            [](TransportFactory* const p) { delete p; });
    return instance;
}

bool TransportFactory::RegisterTransport(std::string name, vbs::transport::TransportDescriptorInterface* descriptor) {
    bool wasRegistered = false;
    logDebug(TRANSPORT, "RegisterTransport for " << name);
    if (!descriptor) {
        return false;
    }
    if (bTransportRegistered(name, descriptor->get_type())) {
        logWarning(TRANSPORT, "Register same transport for type " << static_cast<unsigned int>(descriptor->get_type())
                                                                  << " in " << name);
        return false;
    }
    TransportInterface* transmitor = descriptor->create_transport();

    if (transmitor) {
        if (transmitor->init()) {
            std::lock_guard<std::mutex> guard(mtx_transport_);
            auto array_it = mRegisteredTransports.find(name);

            if (array_it == mRegisteredTransports.end()) {
                // Insert the vector
                std::array<Transport*, static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX)> new_array = {
                    nullptr};
                Transport* ptransport = new Transport();
                ptransport->transmitor(transmitor);
                transmitor->set_transport(ptransport);
                new_array.at(static_cast<unsigned int>(descriptor->get_type())) = ptransport;

                auto pair_it = mRegisteredTransports.insert(std::make_pair(name, std::move(new_array)));
                if (!pair_it.second) {
                    logWarning(TRANSPORT, "insert new transport for " << name << " failed.");
                } else {
                    wasRegistered = true;
                }
            } else {
                if (!(*array_it).second.at(static_cast<unsigned int>(descriptor->get_type()))) {
                    Transport* ptransport = new Transport();
                    ptransport->transmitor(transmitor);
                    transmitor->set_transport(ptransport);
                    (*array_it).second.at(static_cast<unsigned int>(descriptor->get_type())) = ptransport;

                    wasRegistered = true;
                }
            }
        }

        if (!wasRegistered) {
            delete transmitor;
        }
    }

    return wasRegistered;
}

bool TransportFactory::UnregisterTransport(std::string name, TransmitorType type) {
    bool find = false;
    std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    logDebug(TRANSPORT, "UnregisterTransport for " << name);

    if (array_it != mRegisteredTransports.end()) {
        if (static_cast<unsigned int>(type) < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX)) {
            Transport* transport = (*array_it).second.at(static_cast<unsigned int>(type));
            if (transport) {
                logDebug(TRANSPORT, "find transport " << static_cast<unsigned int>(type) << "for " << name);
                find = true;
                (*array_it).second.at(static_cast<unsigned int>(type)) = nullptr;
                transport->m_receiverResourceList_.clear();
                transport->m_sendResourceList_.clear();
                transport->m_sendResourceMap_.clear();
                delete transport->transmitor_;
                delete transport;
            }
        } else {
            logDebug(TRANSPORT, "find all transports for " << name);
            find = true;
            for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
                Transport* transport = (*array_it).second.at(i);
                if (transport) {
                    (*array_it).second.at(i) = nullptr;
                    transport->m_receiverResourceList_.clear();
                    transport->m_sendResourceList_.clear();
                    transport->m_sendResourceMap_.clear();
                    delete transport->transmitor_;
                    delete transport;
                }
            }
            mRegisteredTransports.erase(array_it);
        }
    }

    return find;
}

TransmitorType TransportFactory::LocatorTypeToTransportType(int32_t locator_kind) const {
    switch (locator_kind) {
        case LOCATOR_KIND_UDPv4:
            return TransmitorType::TRANSMITOR_TYPE_UDP;
        case LOCATOR_KIND_UDPv6:
            return TransmitorType::TRANSMITOR_TYPE_UDP;
        case LOCATOR_KIND_TCPv4:
            return TransmitorType::TRANSMITOR_TYPE_TCP;
        case LOCATOR_KIND_TCPv6:
            return TransmitorType::TRANSMITOR_TYPE_TCP;
        case LOCATOR_KIND_SHM:
            return TransmitorType::TRANSMITOR_TYPE_SHM;
#if !defined(_WIN32)
        case LOCATOR_KIND_UDS:
            return TransmitorType::TRANSMITOR_TYPE_UDS;
        case LOCATOR_KIND_UDS_STREAM:
            return TransmitorType::TRANSMITOR_TYPE_UDS_STREAM;
        case LOCATOR_KIND_RAW:
            return TransmitorType::TRANSMITOR_TYPE_RAW;
#endif
        default:
            return TransmitorType::TRANSMITOR_TYPE_MAX;
    }
}

Transport* TransportFactory::GetTransport(std::string name, TransmitorType type) const {
    if (type >= TransmitorType::TRANSMITOR_TYPE_MAX) {
        return nullptr;
    }
    Transport* ptransport = nullptr;
    //using ArrayIt = std::map<std::string, std::array<Transport*, static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX)>>::iterator;
    auto array_it = mRegisteredTransports.find(std::move(name));

    if (array_it != mRegisteredTransports.end()) {
        ptransport = (*array_it).second.at(static_cast<unsigned int>(type));
    }
    return ptransport;
}

bool TransportFactory::bTransportRegistered(std::string name, TransmitorType type) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    Transport* ptransport = GetTransport(std::move(name), type);

    return (ptransport != nullptr);
}

bool TransportFactory::BuildSendResources(std::string name, const Locator_t& locator) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    logDebug(TRANSPORT, ""
                            << "BuildSendResources name-" << name << " locator-" << locator);
    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType(locator.kind));

    if (ptransport) {
        logDebug(TRANSPORT, "find transport start create sender ");

        std::lock_guard<std::mutex> guard(ptransport->lockTransport());

        return ptransport->transmitor()->OpenOutputChannel(ptransport->sendResourceList(), locator);
    }

    return false;
}

bool TransportFactory::BuildSendResources(std::string name, const Locator_t& remote_locator, Locator_t& local_locator) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    logInfo(TRANSPORT, ""
                           << "BuildSendResources name-" << name << " remote_locator-" << remote_locator);
    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType(remote_locator.kind));

    if (ptransport) {
        logInfo(TRANSPORT, "find transport start create sender ");

        std::lock_guard<std::mutex> guard(ptransport->lockTransport());
        return ptransport->transmitor()->OpenOutputChannel(ptransport->sendResourceMap(), remote_locator,
                                                           local_locator);
    }

    return false;
}

bool TransportFactory::CleanSendResource(std::string name, const Locator_t& remote_locator) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    logInfo(TRANSPORT, ""
                           << "CleanSendResource name-" << name << " remote_locator-" << remote_locator);
    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType(remote_locator.kind));

    if (ptransport) {
        logInfo(TRANSPORT, "find transport remove sender ");

        std::lock_guard<std::mutex> guard(ptransport->lockTransport());
        auto sender_resource = ptransport->getSenderResource(remote_locator);
        if (sender_resource) {
            ptransport->sendResourceMap().erase(remote_locator);
            return true;
        }
        return false;
    }

    return false;
}

std::shared_ptr<ReceiverResource> TransportFactory::BuildReceiverResources(std::string name, Locator_t& local,
                                                                           uint32_t receiver_max_message_size,
                                                                           bool& already_open,
                                                                           MessageReceiverInterface* rcv) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    logDebug(TRANSPORT, ""
                            << "BuildReceiverResources name-" << name << " locator-" << local);
    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType(local.kind));

    if (!ptransport) {
        return nullptr;
    }
    logDebug(TRANSPORT, ""
                            << "find transport instance");

    if (!ptransport->transmitor()->IsInputChannelOpen(local)) {
        logDebug(TRANSPORT, ""
                                << "start create channel");

        uint32_t max_recv_buffer_size =
            (std::min)(ptransport->transmitor()->max_recv_buffer_size(), receiver_max_message_size);

        std::shared_ptr<ReceiverResource> newReceiverResource =
            std::make_shared<ReceiverResource>(*ptransport->transmitor(), local, max_recv_buffer_size);
        if (rcv) {
            newReceiverResource->RegisterReceiver(rcv);
        }

        bool ret = ptransport->transmitor()->OpenInputChannel(local, newReceiverResource, max_recv_buffer_size);
        if (ret) {
            newReceiverResource->valid(true);
            ptransport->addReceiver(newReceiverResource);
            return newReceiverResource;
        }
        logDebug(TRANSPORT, ""
                                << "OpenInputChannel  failed.");
    } else {
        already_open = true;
    }

    return nullptr;
}

bool TransportFactory::DestroyReceiverResources(std::string name, Locator_t& local) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType(local.kind));
    if (ptransport) {
        ptransport->transmitor()->CloseInputChannel(local);
        return true;
    }
    return false;
}

bool TransportFactory::Send(std::string name, unsigned char* data, uint32_t dataLength,
                            const LocatorsIterator& destination_locators_begin,
                            const LocatorsIterator& destination_locators_end) {
    LocatorsIterator& it = const_cast<LocatorsIterator&>(destination_locators_begin);
    bool ret = false;

    std::lock_guard<std::mutex> lock(mtx_transport_);
    while (it != destination_locators_end) {
        Transport* ptransport = GetTransport(name, LocatorTypeToTransportType((*it).kind));
        if (ptransport) {

            for (auto& send_resource : ptransport->sendResourceList()) {
                auto retcode = send_resource->send(data, dataLength, &it, &it);
                ret |= retcode;
                /*单播地址只发送一次*/
                if (!IPLocator::isMulticast(*it) && retcode) {
                    logDebug(TRANSPORT, "unicast only send once ...."
                                            << "send to ." << *it);
                    break;
                }
            }
        }
        ++it;
    }
    return ret;
}

bool TransportFactory::Send(std::string name, unsigned char* data, uint32_t dataLength,
                            const Locator_t& destination_locator) {

    bool ret = false;
    ResourceLimitedVector<Locator_t> unicast;
    unicast.push_back(destination_locator);
    Locators begin_it = Locators(unicast.begin());
    Locators end_it = Locators(unicast.end());
    std::lock_guard<std::mutex> lock(mtx_transport_);

    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType((destination_locator).kind));
    if (ptransport) {
        auto sender_resource = ptransport->getSenderResource(destination_locator);
        if (sender_resource) {
            auto retcode = sender_resource->send(data, dataLength, &begin_it, &end_it);
            ret |= retcode;
        }
        for (auto& send_resource : ptransport->sendResourceList()) {
            auto retcode = send_resource->send(data, dataLength, &begin_it, &end_it);
            ret |= retcode;
        }
    }

    return ret;
}

bool TransportFactory::AsyncSend(std::string name, unsigned char* data, uint32_t dataLength,
                                 const LocatorsIterator& destination_locators_begin,
                                 const LocatorsIterator& destination_locators_end, AsyncSendHandler handler) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    LocatorsIterator& it = const_cast<LocatorsIterator&>(destination_locators_begin);
    bool ret = false;
    while (it != destination_locators_end) {
        Transport* ptransport = GetTransport(name, LocatorTypeToTransportType((*it).kind));
        if (ptransport) {
            std::lock_guard<std::mutex> guard(ptransport->lockTransport());
            for (auto& send_resource : ptransport->sendResourceList()) {
                ret |= send_resource->async_send(data, dataLength, &it, &it, handler);
            }
        }
        ++it;
    }
    return ret;
}

bool TransportFactory::AsyncSend(std::string name, unsigned char* data, uint32_t dataLength,
                                 const Locator_t& destination_locator, AsyncSendHandler handler) {

    bool ret = false;
    ResourceLimitedVector<Locator_t> unicast;
    unicast.push_back(destination_locator);
    Locators begin_it = Locators(unicast.begin());
    Locators end_it = Locators(unicast.end());
    std::lock_guard<std::mutex> lock(mtx_transport_);

    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType((destination_locator).kind));

    if (ptransport) {
        auto sender_resource = ptransport->getSenderResource(destination_locator);
        if (sender_resource) {
            auto retcode = sender_resource->async_send(data, dataLength, &begin_it, &end_it, std::move(handler));
            ret |= retcode;
        }
    }

    return ret;
}

void TransportFactory::NormalizeLocators(std::string name, LocatorList_t& locators) {
    LocatorList_t normalizedLocators;

    (void)std::for_each(locators.begin(), locators.end(), [&](Locator_t& loc) {
        bool normalized = false;
        std::lock_guard<std::mutex> guard(mtx_transport_);
        Transport* ptransport = GetTransport(name, LocatorTypeToTransportType(loc.kind));
        if (ptransport) {
            // Check if the locator is supported and filter unicast locators.
            if (ptransport->transmitor()->is_locator_allowed(loc)) {
                // First found transport that supports it, this will normalize the locator.
                normalizedLocators.push_back(ptransport->transmitor()->NormalizeLocator(loc));
                normalized = true;
            }
        }
        if (!normalized) {
            normalizedLocators.push_back(loc);
        }
    });

    locators.swap(normalizedLocators);
}

bool TransportFactory::transform_remote_locator(std::string name, const Locator_t& remote_locator,
                                                Locator_t& result_locator) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType(remote_locator.kind));

    if (ptransport) {
        if (ptransport->transmitor()->transform_remote_locator(remote_locator, result_locator)) {
            return true;
        }
    }

    return false;
}

bool TransportFactory::select_multicast(std::string name, Locator_t& locator) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType(locator.kind));

    if (ptransport) {
        return ptransport->transmitor()->select_multicast();
    }

    return false;
}

bool TransportFactory::is_local_locator(std::string name, const Locator_t& locator) const {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType(locator.kind));

    if (ptransport) {
        return ptransport->transmitor()->is_local_locator(locator);
    }

    return false;
}

bool TransportFactory::is_locator_allowed(std::string name, const Locator_t& locator) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    Transport* ptransport = GetTransport(std::move(name), LocatorTypeToTransportType(locator.kind));

    if (ptransport) {
        return ptransport->transmitor()->is_locator_allowed(locator);
    }

    return false;
}

bool TransportFactory::hasRegisteredTransports(std::string name) {
    std::lock_guard<std::mutex> guard(mtx_transport_);

    //using ArrayIt = std::map<std::string, std::array<Transport*, static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX)>>::iterator;
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* transport = (*array_it).second.at(i);
            if (transport != nullptr) {
                return true;
            }
        }
    }
    return false;
}

void TransportFactory::GetDefaultOutputLocators(std::string name, LocatorList_t& defaultLocators) {
    defaultLocators.clear();
    std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* transport = (*array_it).second.at(i);
            if (transport != nullptr) {
                transport->transmitor()->AddDefaultOutputLocator(defaultLocators);
            }
        }
    }
}

bool TransportFactory::getDefaultMetatrafficMulticastLocators(std::string name, LocatorList_t& locators,
                                                              uint32_t metatraffic_multicast_port) {
    bool result = false;
    std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        logDebug(TRANSPORT, "find  transport for " << name);

        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* transport = (*array_it).second.at(i);

            if (transport != nullptr) {
                logDebug(TRANSPORT, "find  transmitor for type " << i);

                result |= transport->transmitor()->getDefaultMetatrafficMulticastLocators(locators,
                                                                                          metatraffic_multicast_port);
            } else {
                logDebug(TRANSPORT, "NO  transmitor for type " << i);
            }
        }
    } else {
        logInfo(TRANSPORT, "don't find  transport for " << name);
    }
    return result;
}

bool TransportFactory::fillMetatrafficMulticastLocator(std::string name, Locator_t& locator,
                                                       uint32_t metatraffic_multicast_port) {
    bool result = false;

    std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        // For better fault-tolerance reasons, SHM multicast metatraffic is avoided if it is already
        // provided by another transport
        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* transport = (*array_it).second.at(i);
            if (transport != nullptr) {
                result |= transport->transmitor()->fillMetatrafficMulticastLocator(locator, metatraffic_multicast_port);
            }
        }
    }
    return result;
}

bool TransportFactory::getDefaultMetatrafficUnicastLocators(std::string name, LocatorList_t& locators,
                                                            uint32_t metatraffic_unicast_port) {
    bool result = false;
    std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        // For better fault-tolerance reasons, SHM multicast metatraffic is avoided if it is already
        // provided by another transport
        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* transport = (*array_it).second.at(i);
            if (transport != nullptr) {
                result |=
                    transport->transmitor()->getDefaultMetatrafficUnicastLocators(locators, metatraffic_unicast_port);
            }
        }
    }
    return result;
}

bool TransportFactory::fillMetatrafficUnicastLocator(std::string name, Locator_t& locator,
                                                     uint32_t metatraffic_unicast_port) {
    bool result = false;

    std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        // For better fault-tolerance reasons, SHM multicast metatraffic is avoided if it is already
        // provided by another transport
        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* transport = (*array_it).second.at(i);
            if (transport != nullptr) {
                result |= transport->transmitor()->fillMetatrafficUnicastLocator(locator, metatraffic_unicast_port);
            }
        }
    }
    return result;
}

bool TransportFactory::getDefaultUnicastLocators(std::string name, LocatorList_t& locators, uint32_t unicast_port) {
    bool result = false;

    std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        // For better fault-tolerance reasons, SHM multicast metatraffic is avoided if it is already
        // provided by another transport
        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* transport = (*array_it).second.at(i);
            if (transport != nullptr) {
                result |= transport->transmitor()->getDefaultUnicastLocators(locators, unicast_port);
            }
        }
    }
    return result;
}

bool TransportFactory::fill_default_locator_port(std::string name, Locator_t& locator, uint32_t unicast_port) {
    bool result = false;

    std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        // For better fault-tolerance reasons, SHM multicast metatraffic is avoided if it is already
        // provided by another transport
        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* transport = (*array_it).second.at(i);
            if (transport != nullptr) {
                result |= transport->transmitor()->fillUnicastLocator(locator, unicast_port);
            }
        }
    }
    return result;
}

void TransportFactory::Shutdown(std::string name) {
    //std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* ptransport = (*array_it).second.at(i);
            if (ptransport) {
                ptransport->transmitor()->shutdown();
            }
        }
    }
}

void TransportFactory::update_network_interfaces(std::string name) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    auto array_it = mRegisteredTransports.find(name);

    if (array_it != mRegisteredTransports.end()) {
        for (unsigned int i = 0; i < static_cast<unsigned int>(TransmitorType::TRANSMITOR_TYPE_MAX); i++) {
            Transport* ptransport = (*array_it).second.at(i);
            if (ptransport) {
                ptransport->transmitor()->update_network_interfaces();
            }
        }
    }
}

SendResourceList& TransportFactory::getSendResource(std::string name, TransmitorType type) {
    static SendResourceList emptylist;
    std::lock_guard<std::mutex> guard(mtx_transport_);
    Transport* ptransport = GetTransport(std::move(name), type);
    if (ptransport) {
        return ptransport->sendResourceList();
    } else {
        return emptylist;
    }
}

uint32_t TransportFactory::GetMinSendBufferSize(std::string name, TransmitorType type) {
    std::lock_guard<std::mutex> guard(mtx_transport_);
    Transport* ptransport = GetTransport(std::move(name), type);
    if (ptransport) {
        return ptransport->transmitor()->get_configuration()->min_send_buffer_size();
    }
    return 65535u;
}

}  // namespace transport
}  // namespace vbs
